#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#define DRIVER_NAME "mydriver"

BOOLEAN InstallDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName,__in LPCTSTR ServiceExe);
BOOLEAN RemoveDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName);
BOOLEAN StartDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName);
BOOLEAN StopDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName);
BOOLEAN SetupDriverName(__inout_bcount_full(BufferLength) PCHAR DriverLocation, __in ULONG BufferLength);

BOOLEAN LoadDriver(__in LPCTSTR DriverName, __in LPCTSTR ServiceName);
BOOLEAN UnLoadDriver(__in LPCTSTR DriverName, __in LPCTSTR ServiceName);

VOID __cdecl main(__in ULONG argc, __in_ecount(argc) PCHAR argv[])
{
    HANDLE device;
    BOOL rc;
	DWORD written;
    TCHAR location[MAX_PATH];
	TCHAR message[] = "Hello, World!";

    UNREFERENCED_PARAMETER(argc);
    UNREFERENCED_PARAMETER(argv);
	
	if ( !SetupDriverName(location, sizeof(location)) ) return;
	
	if ( (device = CreateFile("\\\\.\\MyDriverTest", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE )
	{	
		if ( !LoadDriver(DRIVER_NAME, location) )
		{
			UnLoadDriver(DRIVER_NAME, location);
			return;
		}
		
		Sleep(3000);
		
		device = CreateFile("\\\\.\\MyDriverTest", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	}
	
	if (device == INVALID_HANDLE_VALUE){
		printf ( "Error: CreatFile Failed : %d\n", GetLastError());
		return;
	}
	
	rc = WriteFile(device, message, (DWORD)strlen(message) + 1, &written, NULL);

	if (rc == FALSE)
    {
        printf("Error: unable to write to file : %d\n", GetLastError());
		return;
    }
	
	Sleep(3000);
	
	//CloseHandle(device);
	//UnLoadDriver(DRIVER_NAME, location);
}

BOOLEAN LoadDriver(__in LPCTSTR DriverName, __in LPCTSTR ServiceName)
{
    SC_HANDLE   schSCManager;

    if (!DriverName || !ServiceName)
	{
        printf("Invalid Driver or Service provided to ManageDriver() \n");
        return FALSE;
    }

    schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!schSCManager)
	{
        printf("Open SC Manager failed! Error = %d \n", GetLastError());
        return FALSE;
    }

	if ( InstallDriver(schSCManager, DriverName, ServiceName) ) return StartDriver(schSCManager, DriverName);

	return FALSE;
}

BOOLEAN UnLoadDriver(__in LPCTSTR DriverName, __in LPCTSTR ServiceName)
{
    SC_HANDLE   schSCManager;

    if (!DriverName || !ServiceName)
	{
        printf("Invalid Driver or Service provided to ManageDriver() \n");
        return FALSE;
    }

    schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!schSCManager)
	{
        printf("Open SC Manager failed! Error = %d \n", GetLastError());
        return FALSE;
    }

	StopDriver(schSCManager, DriverName);
	RemoveDriver(schSCManager, DriverName);
	return TRUE;
}

BOOLEAN InstallDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName, __in LPCTSTR ServiceExe)
{
    SC_HANDLE   schService;
    DWORD       err;

    schService = CreateService(SchSCManager,           // handle of service control manager database
                               DriverName,             // address of name of service to start
                               DriverName,             // address of display name
                               SERVICE_ALL_ACCESS,     // type of access to service
                               SERVICE_KERNEL_DRIVER,  // type of service
                               SERVICE_DEMAND_START,   // when to start service
                               SERVICE_ERROR_NORMAL,   // severity if service fails to start
                               ServiceExe,             // address of name of binary file
                               NULL,                   // service does not belong to a group
                               NULL,                   // no tag requested
                               NULL,                   // no dependency names
                               NULL,                   // use LocalSystem account
                               NULL                    // no password for service account
                               );

    if (schService == NULL) {
        err = GetLastError();
        if (err == ERROR_SERVICE_EXISTS)
		{
            return TRUE;
        }
		else
		{
            printf("CreateService failed!  Error = %d \n", err );
            return  FALSE;
        }
    }
    if (schService) CloseServiceHandle(schService);
    return TRUE;
}

BOOLEAN RemoveDriver(__in SC_HANDLE    SchSCManager, __in LPCTSTR DriverName)
{
    SC_HANDLE   schService;
    BOOLEAN     rCode;

    schService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
    if (schService == NULL)
	{
        printf("OpenService failed!  Error = %d \n", GetLastError());
        return FALSE;
    }

    if (DeleteService(schService))
	{
        rCode = TRUE;
    }
	else
	{
        printf("DeleteService failed!  Error = %d \n", GetLastError());
        rCode = FALSE;
    }

    if (schService) CloseServiceHandle(schService);

    return rCode;
}

BOOLEAN StartDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName)
{
    SC_HANDLE   schService;
    DWORD       err;

    schService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
    if (schService == NULL)
	{
        printf("OpenService failed!  Error = %d \n", GetLastError());
        return FALSE;
    }

    if ( !StartService(schService, 0, NULL) )
	{
        err = GetLastError();
        if (err == ERROR_SERVICE_ALREADY_RUNNING)
		{
            return TRUE;
        }
		else
		{
            printf("StartService failure! Error = %d \n", err );
            return FALSE;
        }
    }
	
    if (schService) CloseServiceHandle(schService);
	
    return TRUE;
}

BOOLEAN StopDriver(__in SC_HANDLE SchSCManager, __in LPCTSTR DriverName)
{
    BOOLEAN         rCode = TRUE;
    SC_HANDLE       schService;
    SERVICE_STATUS  serviceStatus;

    schService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);

    if (schService == NULL)
	{
        printf("OpenService failed!  Error = %d \n", GetLastError());
        return FALSE;
    }

    if ( ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus) )
	{
        rCode = TRUE;
    }
	else
	{
        printf("ControlService failed!  Error = %d \n", GetLastError() );
        rCode = FALSE;
    }
	
    if (schService) CloseServiceHandle (schService);
	
    return rCode;
}

BOOLEAN SetupDriverName(__inout_bcount_full(BufferLength) PCHAR DriverLocation, __in ULONG BufferLength)
{
    HANDLE fileHandle;
    DWORD driverLocLen = 0;

    driverLocLen = GetCurrentDirectory(BufferLength, DriverLocation);
    if (driverLocLen == 0)
	{
        printf("GetCurrentDirectory failed!  Error = %d \n", GetLastError());
        return FALSE;
    }

    if (FAILED( StringCbCat(DriverLocation, BufferLength, "\\"DRIVER_NAME".sys") )) return FALSE;

    if ( (fileHandle = CreateFile(DriverLocation, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL) ) == INVALID_HANDLE_VALUE)
	{
        printf("%s.sys is not loaded.\n", DRIVER_NAME);
        return FALSE;
    }

    if (fileHandle) CloseHandle(fileHandle);

    return TRUE;
}